package com.zbs.framework.common.utils.mp;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import lombok.Data;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author: Zbs
 * @createTime: 2020/12/18 14:54
 * 做一些非空判断，使业务代码块更加简洁
 */
@Data
public class QueryWrapperUtils<T> {
    private QueryWrapper<T> queryWrapper = new QueryWrapper<>();
    private LambdaQueryWrapper<T> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    private LambdaQueryChainWrapper<T> lambdaQueryChainWrapper;


    public QueryWrapperUtils(BaseMapper<T> baseMapper){
        this.lambdaQueryChainWrapper = new LambdaQueryChainWrapper<>(baseMapper);
    }

    public QueryWrapperUtils(){
    }

    public QueryWrapperUtils<T> select(String... columns){
        this.queryWrapper.select(columns);
        return this;
    }

    public QueryWrapperUtils<T> eq(String column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.queryWrapper.eq(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> ne(String column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.queryWrapper.ne(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> gt(String column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.queryWrapper.gt(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> ge(String column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.queryWrapper.ge(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> lt(String column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.queryWrapper.lt(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> le(String column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.queryWrapper.le(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> like(String column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.queryWrapper.like(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> notLike(String column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.queryWrapper.notLike(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> likeLeft(String column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.queryWrapper.likeLeft(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> likeRight(String column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.queryWrapper.likeRight(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> between(String column, Object val1, Object val2){
        this.queryWrapper.between(column,val1,val2);
        return this;
    }

    public QueryWrapperUtils<T> notBetween(String column, Object val1, Object val2){
        this.queryWrapper.notBetween(column,val1,val2);
        return this;
    }

    public QueryWrapperUtils<T> isNull(String column){
        this.queryWrapper.isNull(column);
        return this;
    }
    public QueryWrapperUtils<T> isNotNull(String column){
        this.queryWrapper.isNotNull(column);
        return this;
    }

    public QueryWrapperUtils<T> in(String column,Object... values){
        if (values != null && values.length > 0){
            this.queryWrapper.in(column,values);
        }
        return this;
    }

    public QueryWrapperUtils<T> in(String column, Collection<?> coll){
        if (!CollectionUtils.isEmpty(coll)){
            this.queryWrapper.in(column,coll);
        }
        return this;
    }

    public QueryWrapperUtils<T> notIn(String column,Object... values){
        if (values != null && values.length > 0){
            this.queryWrapper.notIn(column,values);
        }
        return this;
    }

    public QueryWrapperUtils<T> notIn(String column, Collection<?> coll){
        if (!CollectionUtils.isEmpty(coll)){
            this.queryWrapper.notIn(column,coll);
        }
        return this;
    }

    public QueryWrapperUtils<T> groupBy(String... column){
        this.queryWrapper.groupBy(column[0],getColumns(column));
        return this;
    }

    public QueryWrapperUtils<T> orderByAsc(String... column){
        this.queryWrapper.orderByAsc(column[0],getColumns(column));
        return this;
    }

    public QueryWrapperUtils<T> orderByAsc(String column){
        this.queryWrapper.orderByAsc(column);
        return this;
    }

    public QueryWrapperUtils<T> orderByDesc(String... column){
        this.queryWrapper.orderByDesc(column[0],getColumns(column));
        return this;
    }

    public QueryWrapperUtils<T> orderByDesc(String column){
        this.queryWrapper.orderByDesc(column);
        return this;
    }

    @SafeVarargs
    public final QueryWrapperUtils<T> select(SFunction<T, ?>... columns){
        this.lambdaQueryWrapper.select(columns);
        this.lambdaQueryChainWrapper.select(columns);
        return this;
    }

    public QueryWrapperUtils<T> eq(SFunction<T, ?> column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.lambdaQueryWrapper.eq(column,val);
            this.lambdaQueryChainWrapper.eq(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> ne(SFunction<T, ?> column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.lambdaQueryWrapper.ne(column,val);
            this.lambdaQueryChainWrapper.ne(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> gt(SFunction<T, ?> column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.lambdaQueryWrapper.gt(column,val);
            this.lambdaQueryChainWrapper.gt(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> ge(SFunction<T, ?> column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.lambdaQueryWrapper.ge(column,val);
            this.lambdaQueryChainWrapper.ge(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> lt(SFunction<T, ?> column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.lambdaQueryWrapper.lt(column,val);
            this.lambdaQueryChainWrapper.lt(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> le(SFunction<T, ?> column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.lambdaQueryWrapper.le(column,val);
            this.lambdaQueryChainWrapper.le(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> like(SFunction<T, ?> column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.lambdaQueryWrapper.like(column,val);
            this.lambdaQueryChainWrapper.like(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> notLike(SFunction<T, ?> column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.lambdaQueryWrapper.notLike(column,val);
            this.lambdaQueryChainWrapper.notLike(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> likeLeft(SFunction<T, ?> column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.lambdaQueryWrapper.likeLeft(column,val);
            this.lambdaQueryChainWrapper.likeLeft(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> likeRight(SFunction<T, ?> column, Object val){
        if (!ObjectUtils.isEmpty(val)){
            this.lambdaQueryWrapper.likeRight(column,val);
            this.lambdaQueryChainWrapper.likeRight(column,val);
        }
        return this;
    }

    public QueryWrapperUtils<T> between(SFunction<T, ?> column, Object val1, Object val2){
        this.lambdaQueryWrapper.between(column,val1,val2);
        this.lambdaQueryChainWrapper.between(column,val1,val2);
        return this;
    }

    public QueryWrapperUtils<T> notBetween(SFunction<T, ?> column, Object val1, Object val2){
        this.lambdaQueryWrapper.notBetween(column,val1,val2);
        this.lambdaQueryChainWrapper.notBetween(column,val1,val2);
        return this;
    }

    public QueryWrapperUtils<T> isNull(SFunction<T, ?> column){
        this.lambdaQueryWrapper.isNull(column);
        this.lambdaQueryChainWrapper.isNull(column);
        return this;
    }
    public QueryWrapperUtils<T> isNotNull(SFunction<T, ?> column){
        this.lambdaQueryWrapper.isNotNull(column);
        this.lambdaQueryChainWrapper.isNotNull(column);
        return this;
    }

    public QueryWrapperUtils<T> in(SFunction<T, ?> column, Object... values) {
        if (values != null && values.length > 0) {
            this.lambdaQueryWrapper.in(column, values);
            this.lambdaQueryChainWrapper.in(column, values);
        }
        return this;
    }

    public QueryWrapperUtils<T> in(SFunction<T, ?> column, Collection<?> coll){
        if (!CollectionUtils.isEmpty(coll)){
            this.lambdaQueryWrapper.in(column,coll);
            this.lambdaQueryChainWrapper.in(column,coll);
        }
        return this;
    }

    public QueryWrapperUtils<T> notIn(SFunction<T, ?> column,Object... values){
        if (values != null && values.length > 0){
            this.lambdaQueryWrapper.notIn(column,values);
            this.lambdaQueryChainWrapper.notIn(column,values);
        }
        return this;
    }

    public QueryWrapperUtils<T> notIn(SFunction<T, ?> column, Collection<?> coll){
        if (!CollectionUtils.isEmpty(coll)){
            this.lambdaQueryWrapper.notIn(column,coll);
            this.lambdaQueryChainWrapper.notIn(column,coll);
        }
        return this;
    }

    @SafeVarargs
    public final QueryWrapperUtils<T> groupBy(SFunction<T, ?>... column){
        this.lambdaQueryWrapper.groupBy(column[0],this.getSFunction(column));
        this.lambdaQueryChainWrapper.groupBy(column[0],this.getSFunction(column));
        return this;
    }

    @SafeVarargs
    public final QueryWrapperUtils<T> orderByAsc(SFunction<T, ?>... column){
        this.lambdaQueryWrapper.orderByAsc(column[0],this.getSFunction(column));
        this.lambdaQueryChainWrapper.orderByAsc(column[0],this.getSFunction(column));
        return this;
    }


    @SafeVarargs
    public final QueryWrapperUtils<T> orderByDesc(SFunction<T, ?>... column){
        this.lambdaQueryWrapper.orderByDesc(column[0],this.getSFunction(column));
        this.lambdaQueryChainWrapper.orderByDesc(column[0],this.getSFunction(column));
        return this;
    }


    public QueryWrapperUtils<T> having(String sqlHaving, Object... params){
        this.queryWrapper.having(sqlHaving,params);
        this.lambdaQueryChainWrapper.having(sqlHaving,params);
        return this;
    }

    private String[] getColumns(String... column){
        List<String> list = new ArrayList<>();
        for (String s : column) {
            if (!s.equals(column[0])){
                list.add(s);
            }
        }
        if (list.size() == 0){
            return null;
        }
        return list.toArray(new String[column.length]);
    }

    private SFunction<T, ?>[] getSFunction(SFunction<T, ?>... column){
        List<SFunction<T, ?>> list = new ArrayList<>();
        for (SFunction<T, ?> tsFunction : column) {
            if (column[0] != tsFunction){
                list.add(tsFunction);
            }
        }
        if (list.size() == 0){
            return null;
        }
        return list.stream().toArray(SFunction[]::new);
    }
}
